﻿using System;
using System.Collections.Generic;
using Firefly.Libs;
using Microsoft.Xna.Framework;
using Jitter;
using Jitter.LinearMath;
using Ether.Libs;
using Ether.Mapping;

namespace Ether
{
    public static class SelectionEngine {
        public static int CurrentSelection { get; private set; }
        public static int CurrentHover { get; private set; }
        private static List<ISelectable> SelectablesList;

        public static Vector3 CurrentSelectionPosition
        {
            get { return (CurrentSelection == -1) ? (-Vector3.One) : Conversion.ConvertVect(SelectablesList[CurrentSelection].Body.Position); }
        }
        public static Vector3 CurrentHoverPosition
        {
            get { return (CurrentHover == -1) ? (-Vector3.One) : Conversion.ConvertVect(SelectablesList[CurrentHover].Body.Position); }
        }

        public static EtherPosition HoverEtherPosition
        {
            get { return (CurrentHover == -1) ? (-EtherPosition.One()) : SelectablesList[CurrentHover].Position; }
        }
        public static EtherPosition SelectionEtherPosition
        {
            get { return (CurrentSelection == -1) ? (EtherPosition.Zero()) : SelectablesList[CurrentSelection].Position; }
        }

        public static void Clear()
        {
            SelectablesList = new List<ISelectable>();
            CurrentSelection = -1;
            CurrentHover = -1;
        }

        public static void Register(ISelectable item)
        {
            if (SelectablesList == null)
                SelectablesList = new List<ISelectable>();

            SelectablesList.Add(item);
        }
        public static void Register(ISelectable[] item)
        {
            if (SelectablesList == null)
                SelectablesList = new List<ISelectable>();

            foreach(ISelectable i in item)
                SelectablesList.Add(i);
        }

        public static Vector3 RayTo(Game game, Camera camera, Input input)
        {
            float x = input.MouseVect.X;
            float y = input.MouseVect.Y;

            Vector3 nearSource = new Vector3(x, y, 0);
            Vector3 farSource = new Vector3(x, y, 1);

            Matrix world = Matrix.Identity;

            Vector3 nearPoint = game.GraphicsDevice.Viewport.Unproject(nearSource, camera.Projection, camera.View, world);
            Vector3 farPoint = game.GraphicsDevice.Viewport.Unproject(farSource, camera.Projection, camera.View, world);

            Vector3 direction = farPoint - nearPoint;
            return direction;
        }

        public static void SolveSelection(Game game, World gameWorld, Camera camera, Input input)
        {
            bool stopafterRefresh = false;
            for ( int i = 0; i < SelectablesList.Count; i++)
            {
                ISelectable selectable = SelectablesList[i];                
                //If its selected, it stays selected
                if (selectable.SelectState != SelectionState.Selected)
                    selectable.SelectState = SelectionState.None;

                if (stopafterRefresh)
                    continue;

                JVector ray = Conversion.ConvertVect(RayTo(game, camera, input));
                JVector normal;
                float fraction;
                bool result = gameWorld.CollisionSystem.Raycast(selectable.Body, Conversion.ConvertVect(camera.CameraPosition), 
                    ray, out normal, out fraction);

                if (result)
                {
                    if (input.IsLeftClick())
                    {
                        //Deselect
                        if (selectable.SelectState == SelectionState.Selected)
                        {
                            CurrentSelection = -1;
                            selectable.SelectState = SelectionState.Hover;
                        }
                        else
                        {
                            //Deselect current, and select this oSelecne
                            if(CurrentSelection > - 1)
                                SelectablesList[CurrentSelection].SelectState = SelectionState.None;

                            selectable.SelectState = SelectionState.Selected;
                            CurrentSelection = i;
                        }
                    }
                    else
                    {
                        selectable.SelectState = SelectionState.Hover;
                        CurrentHover = i;
                    }

                    stopafterRefresh = true;
                }
            }
        }
    }
}
